package com.zhijiaoyun.common;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.shisfish.util.JwtUtils;
import io.jsonwebtoken.Claims;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.security.MessageDigest;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author shisfish
 * @date 2017/6/6
 */
public class CommonUtils {

	/**
	 * 读取配置文件
	 */
	public static Properties properties = new Properties();
	static {
		try {
			String path = "config.properties";
			InputStream inStream = CommonUtils.class.getClassLoader().getResourceAsStream(path);
			if (inStream == null) {
				inStream = CommonUtils.class.getClassLoader().getResourceAsStream("/" + path);
			}
			properties.load(inStream);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 文件访问路径
	 * @param key
	 * @return
	 */
	public static String getProperty(String key) {
		return properties.getProperty(key);
	}

	/**
	 * 检查路径是否存在，不存在则创建路径
	 * 
	 * @param path
	 */
	public static void checkPath(String path) {
		String[] paths = null;
		if (path.contains("/")) {
			paths = path.split("/");
		} else {
			paths = path.split(File.separator + File.separator);
		}
		if (paths == null || paths.length == 0) {
			return;
		}
		String pathdir = "";
		for (String string : paths) {
			pathdir = pathdir + string + File.separator;
			File file = new File(pathdir);
			if (!file.exists()) {
				file.mkdir();
			}
		}
	}

	public static void createFile(String path) {
		File file = new File(path);
		if (!file.exists()) {
			try {
				file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * MD5加密
	 * 
	 * @param s
	 * 	要加密的
	 * @return 加密后String
	 */
	public final static String MD5(String s) {
		char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
		try {
			byte[] strTemp = s.getBytes();
			// 使用MD5创建MessageDigest对象
			MessageDigest mdTemp = MessageDigest.getInstance("MD5");
			mdTemp.update(strTemp);
			byte[] md = mdTemp.digest();
			int j = md.length;
			char[] str = new char[j * 2];
			int k = 0;
			for (int i = 0; i < j; i++) {
				byte b = md[i];
				str[k++] = hexDigits[b >> 4 & 0xf];
				str[k++] = hexDigits[b & 0xf];
			}
			return new String(str).toUpperCase();
		} catch (Exception e) {
			return null;
		}
	}

	public static String clearHtml(String detail) {
		if (StringUtils.isEmptyString(detail)) {
			Pattern p = Pattern.compile("<[^>]*>");
			Matcher m = p.matcher(detail);
			while (m.find()) {
				detail = detail.replace(m.group(0), "").trim();
			}
		}
		return detail;
	}

	public static String cleanXSS(String value) {
		value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
		value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");
		value = value.replaceAll("'", "& #39;");
		value = value.replaceAll("eval\\((.*)\\)", "");
		value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
		value = value.replaceAll("script", "");
		return value;
	}

	public static Date addYears(Date createTime, Integer maturity) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(createTime);
		cal.add(Calendar.DAY_OF_YEAR, maturity);
		return cal.getTime();
	}
	
	public static Long getUserIdByToken(String token) {
		try {
			Claims claims = JwtUtils.parseJWT(token);
			Object exp = claims.get("exp");
			Long longs = StringUtils.parseLong(exp.toString(), 0) * 1000;
			Date expDate = new Date(longs);
			if (expDate.before(new Date())) {
				return 0L;
			}
			String sub = claims.getSubject();
			JSONObject jsonObject = JSONObject.parseObject(sub);
			Long userId = jsonObject.getLong("userId");
			if (userId == null) {
				return 0L;
			}
			return userId;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return 0L;
	}
	
	public static Long getAdminIdByToken(String token) {
		try {
			Claims claims = JwtUtils.parseJWT(token);
			Object exp = claims.get("exp");
			Long longs = StringUtils.parseLong(exp.toString(), 0) * 1000;
			Date expDate = new Date(longs);
			if (expDate.before(new Date())) {
				return 0L;
			}
			String sub = claims.getSubject();
			JSONObject jsonObject = JSONObject.parseObject(sub);
			Long adminId = jsonObject.getLong("adminId");
			if (adminId == null) {
				return 0L;
			}
			return adminId;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return 0L;
	}
	
	public static String encode(String string) {
		String basicEncoded = Base64.getEncoder().encodeToString(string.getBytes());
		return basicEncoded;
	}
	
	public static void responseOutMap(HttpServletResponse response, Map<String, Object> map) {
		String json = JSON.toJSONString(map);
		response.setCharacterEncoding("UTF-8");  
	    response.setContentType("application/json; charset=utf-8");
        responseOut(response, json);
	}
	
	public static void responseOutHtml(HttpServletResponse response, String html) {
		response.setCharacterEncoding("UTF-8");  
	    response.setContentType("text/html; charset=utf-8");
        responseOut(response, html);
	}

    private static void responseOut(HttpServletResponse response, String html) {
        PrintWriter out = null;
        try {
            out = response.getWriter();
            out.append(html);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }

    public static Map<String, Object> map2Json(Map<String, Object> map) {
		String date = JSONObject.toJSONStringWithDateFormat(map, "yyyy-MM-dd HH:mm:ss", SerializerFeature.WriteDateUseDateFormat);
		JSONObject  jasonObject = JSONObject.parseObject(date);
          
		return jasonObject;
	}
	
	public static String getOrderNum() {
		String orderNum = DateUtils.getDateFormat(new Date(), "yyMMddHHmmssS");
		int random = new Random().nextInt(10);
		return orderNum + String.valueOf(random);
	}
	
	public static void main(String[] args) {
		System.out.println(getOrderNum());
	}

	/**
	 * 获取用户真实IP地址，不使用request.getRemoteAddr();的原因是有可能用户使用了代理软件方式避免真实IP地址,
	 * 参考文章： http://developer.51cto.com/art/201111/305181.htm
	 * 可是，如果通过了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP值，究竟哪个才是真正的用户端的真实IP呢？
	 * 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。
	 *
	 *
	 * 如：X-Forwarded-For：192.168.1.110, 192.168.1.120, 192.168.1.130,
	 * 192.168.1.100
	 *
	 * 用户真实IP为： 192.168.1.110
	 *
	 * @param request
	 * @return
	 */
	public static String getIp(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_CLIENT_IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_X_FORWARDED_FOR");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
	}

}
